﻿using System;
using System.Linq;
using System.Data;
using System.Reflection;
using System.IO;
using System.Configuration;
using System.Data.SqlClient;
using System.Xml.Linq;
using System.Collections.Generic;

using ScrewTurn.Wiki;
using System.Text;
using IdeaNMR.Shared;


namespace IdeaNMR.Web.Core
{
    public class IdeaNMRdbManager
    {
        /// <summary>
        /// Changes flag IsPrivate to targetValue for the component with id componentGuid.
        /// </summary>
        /// <param name="componentGuid"></param>
        /// <param name="username"></param>
        /// <returns>Returns the name of the component with Id componentGuid</returns>
        /// <remarks>Version number is calculated from all the components that have same firtsversionid.</remarks>
        /// <exception cref="System.UnauthorizedAccessException">Thrown when current user is not an author of the component been published.</exception>
        /// <exception cref="System.ArgumentException">Thrown when component with componentGuid is not found.</exception>
        protected static string setIsPrivate(Guid componentGuid, string username, out int VersionNumber, bool targetValue)
        {
            string resultName = string.Empty;

            //IdeaNMRdbContainer ideanmrData = new IdeaNMRdbContainer();

            //var query = (from component in ideanmrData.BaseObjects.OfType<NMRObject>()
            //             where component.Id == componentGuid
            //             select new
            //             {
            //                 Component = component,
            //                 Developments = component.Template.Developments,
            //                 LatestVersion = (int?)(from obj in component.FirstVersion.DerivedVersions.OfType<NMRObject>()
            //                                        let comp = obj
            //                                        where comp.IsPrivate == false
            //                                        select comp.VersionNumber).Max(),
            //                 Authors = from auth in component.Authors
            //                           orderby auth.Index
            //                           select auth.User
            //             }).FirstOrDefault();

            //if (query == null)
            //{
            //    throw new ArgumentException("IdeaNMRdbManager; setIsPrivate; Cannot find an entry with ID = " + componentGuid.ToString(), "componentGuid");
            //}
            //// Check if curent user is author - essential that user can access only those entries, that he is an author of
            //var authorship = from b in query.Authors
            //                 where b.Username == username
            //                 select b;

            //if (authorship.ToArray().Count() == 0) // User is not an author of this entry
            //{
            //    string msg = string.Format("IdeaNMRdbManager; PublishComponent; Unauthorized data access attempt. SECURITY THREAT. ID {{{0}}}.", componentGuid);
            //    throw new UnauthorizedAccessException(msg);
            //}

            //if (query.Component.IsDraft && targetValue == false)
            //{
            //    throw new ArgumentException("IdeaNMRdbManager; PublishComponent; Publishing is not allowed if isDraft is true.", "componentGuid");
            //}

            //query.Component.IsPrivate = targetValue;
            //query.Component.Datetime = DateTime.Now;
            //VersionNumber = query.Component.VersionNumber = (query.LatestVersion == null) ? 0 : (int)query.LatestVersion + 1;

            //// First version is set when first public version is available
            //if (VersionNumber == 0)
            //{
            //    query.Component.FirstVersion = query.Component;
            //    query.Component.Template.FirstVersion = query.Component;
            //    foreach (Component x in query.Developments)
            //    {
            //        x.FirstVersion = query.Component;
            //    }
            //}
            //resultName = query.Component.Name;
            //ideanmrData.SaveChanges();
            VersionNumber = 0;

            return resultName;
        }

        public static void ReInitializeDatabase()
        {
            string query;

            #region Read Sql Query from embedded resource
            query = new StreamReader(Assembly.GetExecutingAssembly().GetManifestResourceStream("IdeaNMR.Core.Web.IdeaNMRdb.edmx.sql")).ReadToEnd();
            #endregion

            #region Execute query
            string[] commands = query.Split(
        new string[] { "GO\r\n", "GO ", "GO\t" }, StringSplitOptions.RemoveEmptyEntries);


            //   string connString = @"Data Source=208.78.30.73,14333;Initial Catalog=IdeaNMRData1;Persist Security Info=True;User ID=inmredm;Password=UcgcQrl2";
            string connString = ConfigurationManager.ConnectionStrings["IdeaNMRSqlConnectionString"].ConnectionString;
            using (SqlConnection conn = new SqlConnection(connString))
            {
                conn.Open();
                try
                {
                    SqlCommand command;
                    foreach (string com in commands)
                    {
                        command = new SqlCommand(com, conn);
                        command.ExecuteNonQuery();
                    }
                }
                finally
                {
                    conn.Close();
                }
            }
            #endregion

            #region Create Admin User
            User admin = new User();
            admin.Username = BuiltinSettings.AdminUsername;
            admin.Firstname = string.Empty;
            admin.Middlename = string.Empty;
            admin.Lastname = string.Empty;
            admin.Datetime = DateTime.Now;
            #endregion

            #region Create BuiltinSettings.SystemUsername user
            User bssu = new User();
            bssu.Username = BuiltinSettings.EngineUsername;
            bssu.Firstname = "Automated";
            bssu.Middlename = "Import";
            bssu.Lastname = "System";
            bssu.Datetime = DateTime.Now;
            //     UserDataManager.AddUserSample(admin);
            //     UserDataManager.AddUserSpec(admin);
            #endregion

            IdeaNMRdbContainer inmr = new IdeaNMRdbContainer();
            inmr.AddToUsers(admin);
            inmr.AddToUsers(bssu);
            inmr.SaveChanges();
        }

        /// <summary>
        /// Gets the detached HardObject by Id, if it belongs to userName.
        /// </summary>
        /// <typeparam name="T">is HardObject</typeparam>
        /// <param name="tID"></param>
        /// <param name="userName"></param>
        /// <returns></returns>
        public static T GetHardObject<T>(Guid tID, string userName)
            where T : HardObject, IHardObjectRelations
        {
            IdeaNMRdbContainer inmr = new IdeaNMRdbContainer();
            T result = (from spec in inmr.BaseObjects.OfType<T>()
                        where spec.Id == tID && (spec.User.Username == userName || !spec.IsPrivate)
                        select spec).FirstOrDefault();
            inmr.Detach(result);
            return result;
        }
        public static T GetHardObject<T>(string tID, string userName)
            where T : HardObject, IHardObjectRelations
        {
            try
            {
                return GetHardObject<T>(new Guid(tID), userName);
            }
            catch (ArgumentNullException)
            { }
            catch (FormatException)
            { }
            catch (OverflowException)
            { }
            return null;
        }
    }

    public static class IdeaNMRExtensions
    {
        /// <summary>
        /// Attaches a detached Entity Object to ObjectContext keeping changes that were made to an object when it was detached.
        /// </summary>
        /// <param name="obj"></param>
        /// <param name="detachedObject"></param>
        /// <exception cref="System.Data.ObjectNotFoundException">Thrown when object is not found in the ObjectContext</exception>
        public static void AttachUpdated(this IdeaNMRdbContainer obj, System.Data.Objects.DataClasses.EntityObject detachedObject)
        {
            if (detachedObject.EntityState != System.Data.EntityState.Detached) return;
            object original = null;
            if (obj.TryGetObjectByKey(detachedObject.EntityKey, out original))
            {
                obj.ApplyCurrentValues(detachedObject.EntityKey.EntitySetName, detachedObject);
            }
            else throw new ObjectNotFoundException();
        }
    }

    public static partial class ComponentTypeExtensions
    {
        public static Type GetSystemType(this ComponentType c)
        {
            Type[] types = { typeof(PulseProgram), typeof(Wave), typeof(Cpd), typeof(Script) };
            return types[(int)c];
        }
    }
}
